/* eslint-disable operator-linebreak */
/* eslint-disable react/no-danger */
/* eslint-disable @typescript-eslint/no-unused-vars */
import React, { useRef } from 'react';
import { Collapse } from 'antd';
import hljs from 'highlight.js';
import MarkdownIt from 'markdown-it';
import flux from '@/assets/images/advanceReact/flux.png';
import flux2 from '@/assets/images/advanceReact/flux2.png';
import reduxCore from '@/assets/images/advanceReact/redux_core.png';
import code1 from '@/assets/images/advanceReact/redux_code1.png';
import code2 from '@/assets/images/advanceReact/redux_code2.png';
import code3 from '@/assets/images/advanceReact/redux_code3.png';
import code4 from '@/assets/images/advanceReact/redux_code4.png';
import code5 from '@/assets/images/advanceReact/redux_code5.png';
import code6 from '@/assets/images/advanceReact/redux_code6.png';
import code7 from '@/assets/images/advanceReact/redux_code7.png';
import code8 from '@/assets/images/advanceReact/redux_code8.png';
import code9 from '@/assets/images/advanceReact/redux_code9.png';
import createStore from '@/assets/images/advanceReact/createStore.png';
import dispatch from '@/assets/images/advanceReact/dispatch.png';
import core2 from '@/assets/images/advanceReact/redux_core2.png';
import subscribe from '@/assets/images/advanceReact/subscribe.png';
import unsubscribe from '@/assets/images/advanceReact/unsubscribe.png';
import redux_thunk1 from '@/assets/images/advanceReact/redux_thunk1.png';
import redux_thunk2 from '@/assets/images/advanceReact/redux_thunk2.png';
import redux_thunk3 from '@/assets/images/advanceReact/redux_thunk3.png';
import redux_thunk4 from '@/assets/images/advanceReact/redux_thunk4.png';
import redux_middleware from '@/assets/images/advanceReact/redux_middleware.png';
import redux_thunk_code1 from '@/assets/images/advanceReact/redux_thunk_code1.png';
import redux_thunk_code2 from '@/assets/images/advanceReact/redux_thunk_code2.png';
import redux_thunk_code3 from '@/assets/images/advanceReact/redux_thunk_code3.png';
import redux_thunk_code4 from '@/assets/images/advanceReact/redux_thunk_code4.png';
import redux_thunk_code5 from '@/assets/images/advanceReact/redux_thunk_code5.png';
import compose from '@/assets/images/advanceReact/compose.png';

import mvc from '@/assets/images/advanceReact/mvc.png';

import 'highlight.js/styles/atom-one-light.css';
import './index.less';

const { Panel } = Collapse;
const mdParser = MarkdownIt({
  html: true,
  linkify: true,
  typographer: true,
  highlight(str, lang) {
    if (lang && hljs.getLanguage(lang)) {
      try {
        return hljs.highlight(lang, str).value;
      } catch (error) {
        console.log(error);
      }
    }
    return ''; // 使用额外的默认转义
  },
});
export default function Redux() {
  return (
    <div className="advance-react-wrapper">
      <Collapse>
        <Panel header="1、架构思想" key="1">
          <p>可以认为Redux时Flux的一种实现形式</p>
          <p>
            Flux并不是一个具体的框架，它是一套由Facebook技术团队提出的应用架构，
            这套架构约束的是应用处理数据的模式
          </p>
          <img src={flux} alt="" width="50%" />
          <img src={flux2} alt="" width="30%" />
          <p>
            flux的核心特征是<code>单项数据流</code>，Flux最核心的地方在于严格的单向数据流
            在单向数据流下，状态的变化是可预测的。Flux架构往往在复杂的项目中才会体现出它的优势和必要性。
          </p>
          <p>MVC模式下的双向数据流：</p>事实上，在许多服务端的MVC应用中，数据流确实能够保持单向
          ，但是在前端场景下，实际的MVC应用要复杂不少前端应用/框架往往出于交互的需要允许View和Model直接通信。
          这将会导致当View层和Modal层庞大时，项目就会很混乱，错综复杂，可能一个小小的改变，就会引起蝴蝶效应。
          <img src={mvc} alt="" width="40%" />
        </Panel>
        <Panel header="2、工作流" key="2">
          <p>
            <code>Store:</code>它是一一个单-的数据源,而且是只读的。
          </p>
          <p>
            <code>Action:</code>是“动作”的意思，它是对变化的描述。
          </p>
          <p>
            <code>Reducer:</code>它负责对变化进行分发和处理，最终将新的数据返回给Store
          </p>
          <img src={reduxCore} alt="" width="30%" />
          <span>
            任何组件都可以以约定的方式从Store读取到全局的状态,
            任何组件也都可以通过合理地派发Action来修改全局的状态
          </span>
        </Panel>
        <Panel header="3、源码" key="3">
          <ul>
            <li>applyMiddleware.js: 中间件模块</li>
            <li>bindActionCreators.js: 将actionCreators和dispatch方法结合</li>
            <li>combineReducers.js: 合并多个reducer</li>
            <li>compose.js: 将函数从右到左组合</li>
            <li>
              createStore.js: 是我们在使用Redux时最先调用的方法
              它是整个流程的入口，也是Redux中最核心的API
            </li>
          </ul>
          <img src={code1} alt="" width="50%" />
          <img src={code2} alt="" width="50%" />
          <img src={code3} alt="" width="50%" />
          <img src={code4} alt="" width="50%" />
          <img src={code5} alt="" width="50%" />
          <img src={code6} alt="" width="50%" />
          <img src={code7} alt="" width="50%" />
          <img src={code8} alt="" width="50%" />
          <img src={code9} alt="" width="50%" />
          <img src={createStore} alt="" width="30%" />
        </Panel>
        <Panel header="4、源码分析" key="4">
          <p>
            <code>dispatch:</code>把action、reducer 和store这三位“主角”给串联起来
          </p>
          <img src={dispatch} alt="" width="30%" />
          <img src={core2} alt="" width="50%" />
          <p>
            用isDispatching将dispatch的过程锁起来，是为了避免开发者在reducer中手动调用dispatch。
          </p>
          <p>作为一个“计算state专用函数”,Redux在设计reducer时就强调了它必须是“纯净”的</p>
          <p>
            subscribe并不是一个严格必要的方法，只有在需要监听状态的变化时，我们才会调用subscribe，因为Redux中已经默认了订阅的对象就是“状态的变化
            (准确地说是dispatch函数的调用) ” 这个事件
          </p>
          <ul>
            <li>
              它们到底是如何与Redux主流程相结合的呢?
              <p> 在store对象创建成功后 通过调用store.subscribe来注册监听函数</p>
              <p>
                当dispatch action发生时 Redux会在reducer执行完毕后
                将listeners数组中的监听函数逐个执行
              </p>
            </li>
            <li>
              为什么会有currentListeners和nextListeners这两个listeners数组?
              <p>
                <img src={subscribe} alt="" width="50%" />
                <img src={unsubscribe} alt="" width="50%" />
                currentListeners数组用于确保监听函数执行过程的稳定性,eg:
                监听函数A和B和C,B中注销A的绑定，如果只有一个nextListeners，就会影响for循环中listener函数的执行，因为此时nextListeners只有B和C了，无法在执行C了
              </p>
              <p>
                currentListeners就是为了记录下当前正在工作中的listeners数组的引用
                将它与可能发生改变的nextListeners区分开来 以确保监听函数在执行过程中的稳定性
              </p>
            </li>
          </ul>
        </Panel>
        <Panel header="5、中间件" key="5">
          <p>
            异步Action：Redux源码中只有同步操作，如果想要在Redux中引入异步数据流，需要使用中间件来增强createStore。
          </p>
          <img src={redux_thunk1} alt="" width="40%" />
          <img src={redux_thunk2} alt="" width="40%" />
          <img src={redux_thunk3} alt="" width="40%" />
          <img src={redux_thunk4} alt="" width="40%" />
          <p>dispatch的入参从action对象变成了一个函数，action入参必须是一个对象。</p>
          <img src={redux_middleware} alt="" width="40%" />
          <p>dispatch并非被“绕过”了，而是被“改写”了 改写它的不是别人，正是applyMiddleware</p>
          <p>
            1、<code>中间件的执行时机</code>：即action被分发之后、reducer触发之前。 2、
            <code>中间件的执行前提</code>
            ：即applyMiddleware将会对dispatch函数进行改写，使得dispatch在触发reducer之前会首先执行对Redux中间件的链式调用。
          </p>
          <img src={redux_thunk_code1} alt="" width="40%" />
          <img src={redux_thunk_code2} alt="" width="40%" />
          <img src={redux_thunk_code3} alt="" width="40%" />
          <img src={redux_thunk_code4} alt="" width="40%" />
          <img src={redux_thunk_code5} alt="" width="40%" />
          <p>
            外层函数的主要作用是获取dispatch、getState 这两个API
            而真正的中间件逻辑是在内层函数（返回的函数）中包裹的。
          </p>
          <p>
            待<code>middlewares.map(middleware =&gt; middleware(middlewareAPI)) </code>执行完毕后
            内层函数会被悉数提取至chain数组。
          </p>
          <img src={compose} alt="" width="40%" />
          <p>
            面向切面思想在很大程度.上 提升了我们组织逻辑的灵活度与干净度
            帮助我们规避掉了逻辑冗余、逻辑耦合这类问题
          </p>
        </Panel>
      </Collapse>
    </div>
  );
}
